#lang sicp
;; explicit dispatch
(define (real-part x)
  (cond ((rectangular? x) (real-part-rectangular (get-contents x)))
        ((polar? x) (real-part-polar (get-contents x)))
        (else (error "unknown value -- REAL-PART" x))))
(define (imag-part x)
  (cond ((rectangular? x) (imag-part-rectangular (get-contents x)))
        ((polar? x) (imag-part-polar (get-contents x)))
        (else (error "unknown value -- REAL-PART" x))))
(define (magnitude x)
  (cond ((rectangular? x) (magnitude-rectangular (get-contents x)))
        ((polar? x) (magnitude-polar (get-contents x)))
        (else (error "unknown value -- REAL-PART" x))))
(define (angle x)
  (cond ((rectangular? x) (angle-rectangular (get-contents x)))
        ((polar? x) (angle-polar (get-contents x)))
        (else (error "unknown value -- REAL-PART" x))))



;; type predicate, add when new type is added
(define (rectangular? x)
  (is-type? x 'rectangular))
(define (polar? x)
  (is-type? x 'polar))

(define (make-from-real-imag real imag)
  (attach-tag 'rectangular (make-from-real-imag-rectangular real imag)))
(define (make-from-mag-ang r a)
  (attach-tag 'polar (make-from-mag-ang-polar r a)))



;;
(define (make-from-real-imag-rectangular real imag) (cons real imag))
(define (make-from-mag-ang-rectangular r a)
  (cons (* r (cos a)) (* r (sin a))))
(define (real-part-rectangular x) (car x))
(define (imag-part-rectangular x) (cdr x))
(define (magnitude-rectangular x)
  (sqrt (+ (square (real-part-rectangular x))
           (square (imag-part-rectangular x)))))
(define (angle-rectangular x)
  (atan (imag-part-rectangular x) (real-part-rectangular x)))

;;
(define (real-part-polar z) (* (magnitude-polar z) (cos (angle-polar z))))
(define (imag-part-polar z) (* (magnitude-polar z) (sin (angle-polar z))))
(define (magnitude-polar z) (car z))
(define (angle-polar z) (cdr z))
(define (make-from-real-imag-polar x y)
  (cons (sqrt (+ (square x) (square y)))
        (atan y x)))
(define (make-from-mag-ang-polar r a) (cons r a))


;; tag
(define (attach-tag tag contents)
  (cons tag contents))
(define (type-tag x) (car x))
(define (get-contents x) (cdr x))
(define (is-type? x tag)
  (and (pair? x) (eq? tag (type-tag x))))


;;
(define (square x) (* x x))




;; test
(define a (make-from-real-imag 3 4))
(define b (make-from-mag-ang 5 0.927))